﻿//
// Created by bxc on 2022/12/15.
//

#ifndef BXC_GB28181CLIENT_RTPSENDPS_H
#define BXC_GB28181CLIENT_RTPSENDPS_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "RTSPStream.h"
#ifndef WIN32 // Linux系统
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#endif // !WIN32

#include <thread>
class DataSender;
/***
*@remark:  讲传入的数据按位一个一个的压入数据
*@param :  buffer   [in]  压入数据的buffer
*          count    [in]  需要压入数据占的位数
*          bits     [in]  压入的数值
*/
#define bits_write(buffer, count, bits)\
{\
	bits_buffer_s *p_buffer = (buffer); \
	int i_count = (count); \
	uint64_t i_bits = (bits); \
while (i_count > 0)\
{\
	i_count--; \
if ((i_bits >> i_count) & 0x01)\
{\
	p_buffer->p_data[p_buffer->i_data] |= p_buffer->i_mask; \
}\
	else\
{\
	p_buffer->p_data[p_buffer->i_data] &= ~p_buffer->i_mask; \
}\
	p_buffer->i_mask >>= 1;         /*操作完一个字节第一位后，操作第二位*/\
if (p_buffer->i_mask == 0)     /*循环完一个字节的8位后，重新开始下一位*/\
{\
	p_buffer->i_data++; \
	p_buffer->i_mask = 0x80; \
}\
}\
}

namespace BXC {

	#define H264 0
	#define H265 1
	#define MEDIATYPE H264

    #define PS_HDR_LEN  14 // ps header 字节长度
    #define SYS_HDR_LEN 18 // ps system header 字节长度
    #define PSM_HDR_LEN 24 // ps system map    字节长度
    #define PES_HDR_LEN 19 // ps pes header    字节长度
    #define RTP_HDR_LEN 12 // rtp header       字节长度
    #define RTP_VERSION 2  // rtp 版本号
    #define RTP_MAX_PACKET_BUFF 1460 // rtp传输时的最大包长
    #define PS_PES_PAYLOAD_SIZE 65522 // 分片进循发送的最大长度上限
	//I帧（关键帧）：H264_NAL_SLICE_IDR(值为 5)
	//P帧：H264_NAL_SLICE(值为 1)
	//B帧：H264_NAL_SLICE_DPA(值为 2), H264_NAL_SLICE_DPB(值为 3), H264_NAL_SLICE_DPC(值为 4)
	enum H264_NAL_TYP
	{
		H264_NAL_UNKNOWN = 0, // 未使用
		H264_NAL_SLICE = 1, // 不分区、非 IDR 图像的片（片的头信息和数据）
		H264_NAL_SLICE_DPA = 2, // 片分区 A
		H264_NAL_SLICE_DPB = 3, // 片分区 B
		H264_NAL_SLICE_DPC = 4, // 片分区 C
		H264_NAL_SLICE_IDR = 5,  // IDR 图像中的片
		H264_NAL_SEI = 6,// 补充增强信息单元

		//参数集是 H.264 标准的一个新概念，是一种通过改进视频码流结构增强错误恢复能力的方法。
		H264_NAL_SPS = 7, // 序列参数集 （包括一个图像序列的所有信息，即两个 IDR 图像间的所有图像信息，如图像尺寸、视频格式等）
		H264_NAL_PPS = 8, // 图像参数集 （包括一个图像的所有分片的所有相关信息， 包括图像类型、序列号等，解码时某些序列号的丢失可用来检验信息包的丢失与否）

		H264_NAL_AUD = 9, // 分界符
		H264_NAL_SEQ_END = 10,//序列结束(表明下一图像为IDR图像)
		H264_NAL_STREAM_END = 11,//码流结束(表明该流中已没有图像)
		H264_NAL_FILLER = 12, // 填充（哑元数据，用于填充字节）
							//13～23 //保留
							//24~31 //未使用
	};
	enum HEVC_NAL_TYPE
	{
		HEVC_NAL_TRAIL_N = 0,
		HEVC_NAL_TRAIL_R = 1,    //P frame
		HEVC_NAL_TSA_N = 2,
		HEVC_NAL_TSA_R = 3,
		HEVC_NAL_STSA_N = 4,
		HEVC_NAL_STSA_R = 5,
		HEVC_NAL_RADL_N = 6,
		HEVC_NAL_RADL_R = 7,
		HEVC_NAL_RASL_N = 8,
		HEVC_NAL_RASL_R = 9,
		HEVC_NAL_VCL_N10 = 10,
		HEVC_NAL_VCL_R11 = 11,
		HEVC_NAL_VCL_N12 = 12,
		HEVC_NAL_VCL_R13 = 13,
		HEVC_NAL_VCL_N14 = 14,
		HEVC_NAL_VCL_R15 = 15,
		HEVC_NAL_BLA_W_LP = 16,
		HEVC_NAL_BLA_W_RADL = 17,
		HEVC_NAL_BLA_N_LP = 18,
		HEVC_NAL_IDR_W_RADL = 19,    //IDR
		HEVC_NAL_IDR_N_LP = 20,
		HEVC_NAL_CRA_NUT = 21,
		HEVC_NAL_IRAP_VCL22 = 22,
		HEVC_NAL_IRAP_VCL23 = 23,
		HEVC_NAL_RSV_VCL24 = 24,
		HEVC_NAL_RSV_VCL25 = 25,
		HEVC_NAL_RSV_VCL26 = 26,
		HEVC_NAL_RSV_VCL27 = 27,
		HEVC_NAL_RSV_VCL28 = 28,
		HEVC_NAL_RSV_VCL29 = 29,
		HEVC_NAL_RSV_VCL30 = 30,
		HEVC_NAL_RSV_VCL31 = 31,
		HEVC_NAL_VPS = 32,    //VPS
		HEVC_NAL_SPS = 33,    //SPS
		HEVC_NAL_PPS = 34,    //PPS
		HEVC_NAL_AUD = 35,
		HEVC_NAL_EOS_NUT = 36,
		HEVC_NAL_EOB_NUT = 37,
		HEVC_NAL_FD_NUT = 38,
		HEVC_NAL_SEI_PREFIX = 39,    //SEI
		HEVC_NAL_SEI_SUFFIX = 40,
	};

    union LESize
    {
        unsigned short int  length;
        unsigned char   byte[2];
    };

    struct bits_buffer_s {
        unsigned char* p_data;
        unsigned char  i_mask;
        int i_size;
        int i_data;
    };

    struct Data_Info_s {
        uint64_t s64CurPts;
		uint64_t s64CurDts;
        int      IFrame;
        uint16_t u16CSeq;
        uint32_t u32Ssrc;
        char szBuff[RTP_MAX_PACKET_BUFF];
    };



    class RtpSendPs{
    public:
		int SendDataBuff(char* buff, int size);
        explicit RtpSendPs(const char* rtpServerIp,int rtpServerPort,int localRtpPort, const char* rtspurl,std::string proto);
		bool isRtpProtoTCP(void);
        RtpSendPs() = delete;
        ~RtpSendPs();
		
    public:
        void start();
        void stop();
    private:
        int findStartCode(unsigned char* buf, int zeros_in_startcode);
        int getNextNalu(FILE* inpf, unsigned char* buf, unsigned char* naltype);
		int getNextNalu(unsigned char* source, unsigned char* buf, unsigned char* naltype, int countsize, int size);

        int gb28181_streampackageForH264(char* pData, int nFrameLen, Data_Info_s* pPacker, int stream_type);
        int gb28181_make_ps_header(char* pData, unsigned long long s64Scr);
        int gb28181_make_sys_header(char* pData);
        int gb28181_make_psm_header(char* pData);
        int gb28181_make_pes_header(char* pData, int stream_id, int payload_len, unsigned long long pts, unsigned long long dts);
        int gb28181_send_rtp_pack(char* databuff, int nDataLen, int mark_flag, Data_Info_s* pPacker);
        int gb28181_make_rtp_header(char* pData, int marker_flag, unsigned short cseq, long long curpts, unsigned int ssrc);
        

        static void SendDataThread(void *arg);
    private:
		bool mIsRtpTranportTCP;
		RTSPStream * mRTSPStream;
        //int mSockFd = -1;
		DataSender* mpRtpSender;
        const char * mRtpServerIp;
        int          mRtpServerPort = 0;
        int          mLocalRtpPort = 0;

        std::thread * mThread = nullptr;
        bool mQuit;
    };


}
#endif //BXC_GB28181CLIENT_RTPSENDPS_H